/***************************************************************************************************
 * Copyright 2025-2025 x-tools-author(x-tools@outlook.com). All rights reserved.
 *
 * The file is encoded using "utf8 with bom", it is a part of xModbus project.
 *
 * xModbus is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
 * code directory.
 **************************************************************************************************/
#include "modbusregister.h"

#include "modbuscommon.h"

namespace xModbus {

ModbusRegister::ModbusRegister(QObject *parent)
    : QObject(parent)
{
    load(QJsonObject());
}

ModbusRegister::ModbusRegister(const ModbusRegister &other)
{
    type = other.type;
    name = other.name;
    unit = other.unit;
    description = other.description;
    address = other.address;
    min = other.min;
    max = other.max;
    decimals = other.decimals;
    value = other.value;
    serverAddress = other.serverAddress;
}

ModbusRegister::~ModbusRegister() {}

void ModbusRegister::load(const QJsonObject &json)
{
    QString addressName = QString("0x%1").arg(address, 4, 16, QChar('0').toUpper());
    QString defaultName = QString("%1 - %2").arg(registerTypeToString(type)).arg(addressName);
    RegisterItemKeys keys;
    int defaultType = static_cast<int>(QModbusDataUnit::Invalid);
    type = static_cast<QModbusDataUnit::RegisterType>(json.value(keys.type).toInt(defaultType));
    name = json.value(keys.name).toString(defaultName);
    unit = json.value(keys.unit).toString("");
    description = json.value(keys.description).toString("");
    address = static_cast<quint16>(json.value(keys.address).toInt(1));
    min = json.value(keys.min).toDouble(0);
    max = json.value(keys.max).toDouble(65535);
    decimals = json.value(keys.decimals).toInt(0);
    value = static_cast<qint16>(json.value(keys.value).toInt(0));
    serverAddress = json.value(keys.serverAddress).toInt(1);
}

QJsonObject ModbusRegister::save()
{
    RegisterItemKeys keys;
    QJsonObject json;
    json.insert(keys.type, static_cast<int>(type));
    json.insert(keys.name, name);
    json.insert(keys.unit, unit);
    json.insert(keys.description, description);
    json.insert(keys.address, static_cast<int>(address));
    json.insert(keys.min, min);
    json.insert(keys.max, max);
    json.insert(keys.decimals, decimals);
    json.insert(keys.value, value);
    json.insert(keys.serverAddress, serverAddress);
    return json;
}

quint16 ModbusRegister::getValue() const
{
    m_valueMutex.lock();
    quint16 value = this->value;
    m_valueMutex.unlock();
    return value;
}

void ModbusRegister::setValue(quint16 newValue)
{
    if (type == QModbusDataUnit::Coils || type == QModbusDataUnit::DiscreteInputs) {
        newValue = (newValue != 0) ? 1 : 0;
    }

    bool changed = false;
    m_valueMutex.lock();
    if (value != newValue) {
        value = newValue;
        changed = true;
    }
    m_valueMutex.unlock();

    if (changed) {
        emit valueChanged();
    }
}

QString ModbusRegister::getName() const
{
    m_valueMutex.lock();
    QString name = this->name;
    m_valueMutex.unlock();
    return name;
}

void ModbusRegister::setName(const QString &newName)
{
    bool changed = false;
    m_valueMutex.lock();
    if (name != newName) {
        name = newName;
        changed = true;
    }
    m_valueMutex.unlock();

    if (changed) {
        emit nameChanged();
    }
}

} // namespace xModbus